<#assign object = doc.object>
package ${object.package}.service.base;

import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
<#if object.attributes.xml[0]??>
import java.io.ByteArrayOutputStream;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;

import redora.rdo.util.DefaultErrorHandler;
import redora.rdo.util.SchemaValidator;

import ${object.package}.model.xml.*;
</#if>
import redora.rdo.api.*;
import redora.rdo.api.BusinessRuleViolation.Action;
import redora.rdo.api.BusinessRuleViolation.StandardRule;
import redora.rdo.exceptions.BusinessRuleViolationException;

import ${object.package}.model.*;
import ${object.package}.model.fields.${object.name}Fields;

public abstract class ${object.name}BusinessRulesBase {
	private Logger l = Logger.getLogger("${object.package}.service.base.${object.name}BusinessRulesBase");
	<#list object.attributes?children as att>
	<#if att?node_name == "date" && att.@regexp[0]??>
	private java.text.SimpleDateFormat dateFormat = new java.text.SimpleDateFormat("yyyy-mm-dd hh:mm:ss");
	private java.util.regex.Pattern ${att.@name}Pattern = java.util.regex.Pattern.compile("${att.@regexp}");
	<#elseif att?node_name == "string" && att.@regexp[0]??>
	private java.util.regex.Pattern ${att.@name}Pattern = java.util.regex.Pattern.compile("${att.@regexp}");
	<#elseif att?node_name == "xml">
	private SchemaValidator <#if att.@class[0]??>${att.@class?uncap_first}<#else>${att.@name}</#if>Validator;
	</#if>
	</#list>
	
	private Set<BusinessRuleViolation> onAll(${object.name} pojo, Action action) throws BusinessRuleViolationException {
		Set<BusinessRuleViolation> retVal = new HashSet<BusinessRuleViolation>();
		<#list object.attributes?children as att>
			<#if att?node_name != "set" && att?node_type == "element">
				<#if att.@notnull[0]?? && att.@notnull[0] == "true">
					<#if att?node_name == "string">
		if (pojo.${att.@name} == null || pojo.${att.@name}.trim().length() <= 0)
			retVal.add(new BusinessRuleViolation(
				${object.name}.class, pojo.getId(), ${object.name}Fields.${att.@name}, StandardRule.NotNull.ruleId, action));
					<#elseif att?node_name == "object">
		if (pojo.${att.@name[0]!att.@class?uncap_first} == null)
			retVal.add(new BusinessRuleViolation(
				${object.name}.class, pojo.getId(), ${object.name}Fields.${att.@name[0]!att.@class?uncap_first}Id, StandardRule.NotNull.ruleId, action));
					<#else>
		if (pojo.${att.@name[0]!att.@class?uncap_first} == null)	
			retVal.add(new BusinessRuleViolation(
				${object.name}.class, pojo.getId(), ${object.name}Fields.${att.@name[0]!att.@class?uncap_first}, StandardRule.NotNull.ruleId, action));
					</#if>
				</#if>
				<#if att.@regexp[0]??>
		if (pojo.dirty.contains(${object.name}Fields.${att.@name}) && pojo.${att.@name} != null) {
					<#if att?node_name == "date">
			try {
				java.util.regex.Matcher ${att.@name}Matcher = ${att.@name}Pattern.matcher(dateFormat.format(pojo.${att.@name}));
				if(!${att.@name}Matcher.matches())
					retVal.add(new BusinessRuleViolation(${object.name}.class, pojo.getId(),
						${object.name}Fields.${att.@name}, StandardRule.MatchRegexp.ruleId, action));
			} catch(Exception e) {
				l.log(Level.SEVERE, "Failed to check date ${att.@name}'s for regexp ${att.@regexp} ", e);
				throw new BusinessRuleViolationException("Failed to check date ${att.@name}'s regexp ${att.@regexp}",e);
			}
					<#elseif att?node_name == "string">
			java.util.regex.Matcher ${att.@name}Matcher = ${att.@name}Pattern.matcher(pojo.${att.@name});
			if (!${att.@name}Matcher.matches())
				retVal.add(new BusinessRuleViolation(${object.name}.class, pojo.getId(),
					${object.name}Fields.${att.@name}, StandardRule.MatchRegexp.ruleId, action));
					<#else>
					HOLA: unspecified regexp in ${att.@name}. Check the model, XSD or fix this template
					</#if>
		}
				</#if>
				<#if att.@maxlength[0]??>
		if (pojo.dirty.contains(${object.name}Fields.${att.@name}) && pojo.${att.@name} != null && pojo.${att.@name}.length() > ${att.@maxlength})
			retVal.add(new BusinessRuleViolation(${object.name}.class, pojo.getId(),
				${object.name}Fields.${att.@name}, StandardRule.MaxLength.ruleId, action));	
				</#if>
				<#if att?node_name == "xml">
		if (pojo.dirty.contains(${object.name}Fields.${att.@name})) {
			try {
				<#if att.@class[0]??>${att.@class?uncap_first}<#else>${att.@name}</#if>Validator = new SchemaValidator(getClass(),"<#if att.@class[0]??>${att.@class}<#else>${att.@name?cap_first}</#if>.xsd");
				ByteArrayOutputStream out = new ByteArrayOutputStream();
				JAXBContext jc = JAXBContext.newInstance(<#if att.@class[0]??>${att.@class}<#else>${att.@name?cap_first}</#if>.class);
				Marshaller m = jc.createMarshaller();
				m.marshal(pojo.get${att.@name?cap_first}(), out);

				DefaultErrorHandler errorHandler = new DefaultErrorHandler();
				<#if att.@class[0]??>${att.@class?uncap_first}<#else>${att.@name}</#if>Validator.validate(new java.io.ByteArrayInputStream(out
						.toByteArray()), errorHandler);
				if (errorHandler.getErrors().hasContent()) {
					l.log(Level.FINE,"Failed to do checking according to XSD file for ${att.@name}");
					retVal.add(new BusinessRuleViolation(${object.name}.class,
							pojo.getId(), ${object.name}Fields.${att.@name},
							StandardRule.XsdValidation.ruleId, action));
				}
			} catch (Exception e) {
				l.log(Level.SEVERE, "Failed to do XSD check for <#if att.@class[0]??>${att.@class}<#else>${att.@name?cap_first}</#if>. Your XSD is maybe not in the classpath yet, so run maven build first.", e);
				throw new BusinessRuleViolationException("Failed to do XSD check for <#if att.@class[0]??>${att.@class}<#else>${att.@name?cap_first}</#if>. Your XSD is maybe not in the classpath yet, so run maven build first.", e);
			}	
		}
				</#if>
			</#if>
		</#list>
	
		return retVal;
	}

	public Set<BusinessRuleViolation> onInsert(${object.name} pojo) throws BusinessRuleViolationException {
		return onAll(pojo, Action.Insert);
	}
	public Set<BusinessRuleViolation> onUpdate(${object.name} pojo) throws BusinessRuleViolationException {
		return onAll(pojo, Action.Update);
	}
	public Set<BusinessRuleViolation> onDelete(${object.name} pojo) throws BusinessRuleViolationException {
		return new HashSet<BusinessRuleViolation>();
	}
}
